using System;
using System.Runtime.CompilerServices;

namespace System.Data
{
	public static class DataRowExtensions
	{
		public static T Field<T> (this DataRow row, int columnIndex)
		{
			return Field<T> (row, columnIndex, DataRowVersion.Current);
		}

		public static T Field<T> (this DataRow row, int columnIndex, DataRowVersion version)
		{
			object ret = row [columnIndex, version];
			if (ret == DBNull.Value) {
				Type type = typeof (T);
				Type genericTypeDef = type.IsGenericType ? type.GetGenericTypeDefinition () : null;
				if (!type.IsValueType || genericTypeDef != null && genericTypeDef == typeof (Nullable <>))
					return default (T);
				
				throw new StrongTypingException ("Cannot get strong typed value since it is DB null. Please use a nullable type.", null);
			}
			
			return (T) ret;
		}

		public static T Field<T> (this DataRow row, string columnName)
		{
			return Field<T> (row, columnName, DataRowVersion.Current);
		}

		public static T Field<T> (this DataRow row, string columnName, DataRowVersion version)
		{
			return Field<T> (row, row.Table.Columns [columnName], version);
		}

		public static T Field<T> (this DataRow row, DataColumn column)
		{
			return Field<T> (row, column, DataRowVersion.Current);
		}

		public static T Field<T> (this DataRow row, DataColumn column, DataRowVersion version)
		{
			return Field<T> (row, row.Table.Columns.IndexOf (column), version);
		}

		public static void SetField<T> (this DataRow row, int columnIndex, T value)
		{
			row [columnIndex] = value;
		}

		public static void SetField<T> (this DataRow row, string columnName, T value)
		{
			row [columnName] = value;
		}

		public static void SetField<T> (this DataRow row, DataColumn column, T value)
		{
			row [column] = value;
		}
	}
}
